home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / fsio / fsioFile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-19  |  58.3 KB  |  1,882 lines

  1. /* 
  2.  * fsioFile.c --
  3.  *
  4.  *    Routines for operations on files.  A file handle is identified
  5.  *    by using the <major> field of the Fs_FileID for the domain index,
  6.  *    and the <minor> field for the file number.
  7.  *
  8.  * Copyright 1987 Regents of the University of California
  9.  * All rights reserved.
  10.  * Permission to use, copy, modify, and distribute this
  11.  * software and its documentation for any purpose and without
  12.  * fee is hereby granted, provided that the above copyright
  13.  * notice appear in all copies.  The University of California
  14.  * makes no representations about the suitability of this
  15.  * software for any purpose.  It is provided "as is" without
  16.  * express or implied warranty.
  17.  */
  18.  
  19. #ifndef lint
  20. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/fsio/fsioFile.c,v 9.42 92/08/10 17:26:50 mgbaker Exp $ SPRITE (Berkeley)";
  21. #endif not lint
  22.  
  23.  
  24. #include <sprite.h>
  25. #include <fs.h>
  26. #include <fsutil.h>
  27. #include <fsconsist.h>
  28. #include <fsio.h>
  29. #include <fsioFile.h>
  30. #include <fslcl.h>
  31. #include <fsNameOps.h>
  32. #include <fscache.h>
  33. #include <fsprefix.h>
  34. #include <fsioLock.h>
  35. #include <fsdm.h>
  36. #include <fsrmt.h>
  37. #include <fsStat.h>
  38. #include <vm.h>
  39. #include <rpc.h>
  40. #include <recov.h>
  41.  
  42. #include <stdio.h>
  43. #include <fsrecov.h>
  44. void IncVersionNumber _ARGS_((Fsio_FileIOHandle    *handlePtr));
  45.  
  46. /*
  47.  *----------------------------------------------------------------------
  48.  *
  49.  * Fsio_LocalFileHandleInit --
  50.  *
  51.  *    Initialize a handle for a local file from its descriptor on disk.
  52.  *
  53.  * Results:
  54.  *    An error code from the read of the file descriptor off disk.
  55.  *
  56.  * Side effects:
  57.  *    Create and install a handle for the file.  It is returned locked
  58.  *    and with its reference count incremented if SUCCESS is returned.
  59.  *
  60.  *----------------------------------------------------------------------
  61.  */
  62. ReturnStatus
  63. Fsio_LocalFileHandleInit(fileIDPtr, name, descPtr, cantBlock, newHandlePtrPtr)
  64.     Fs_FileID    *fileIDPtr;
  65.     char    *name;
  66.     Fsdm_FileDescriptor *descPtr;
  67.     Boolean    cantBlock;
  68.     Fsio_FileIOHandle    **newHandlePtrPtr;
  69. {
  70.     register ReturnStatus status;
  71.     register Fsio_FileIOHandle *handlePtr;
  72.     register Fsdm_Domain *domainPtr;
  73.     register Boolean found;
  74.     Boolean allocated = FALSE;
  75.  
  76.     found = Fsutil_HandleInstall(fileIDPtr, sizeof(Fsio_FileIOHandle), name,
  77.             cantBlock, (Fs_HandleHeader **)newHandlePtrPtr);
  78.     if (found) {
  79.     if ((*newHandlePtrPtr) == (Fsio_FileIOHandle *) NIL) {
  80.         return FS_WOULD_BLOCK;
  81.     }
  82.     /*
  83.      * All set.
  84.      */
  85.     if ((*newHandlePtrPtr)->descPtr == (Fsdm_FileDescriptor *)NIL) {
  86.         panic("Fsio_LocalFileHandleInit, found handle with no descPtr\n");
  87.     }
  88.     return(SUCCESS);
  89.     }
  90.     status = SUCCESS;
  91.     handlePtr = *newHandlePtrPtr;
  92.     domainPtr = Fsdm_DomainFetch(fileIDPtr->major, FALSE);
  93.     if (domainPtr == (Fsdm_Domain *)NIL) {
  94.     Fsutil_HandleRelease(handlePtr, FALSE);
  95.     Fsutil_HandleRemove(handlePtr);
  96.     return(FS_DOMAIN_UNAVAILABLE);
  97.     }
  98.     if (descPtr == (Fsdm_FileDescriptor *) NIL) { 
  99.     /*
  100.      * Get a hold of the disk file descriptor.
  101.      */
  102.     allocated = TRUE;
  103.     descPtr = (Fsdm_FileDescriptor *)malloc(sizeof(Fsdm_FileDescriptor));
  104.     status = Fsdm_FileDescFetch(domainPtr, fileIDPtr->minor, descPtr);
  105.     if (status == FS_FILE_NOT_FOUND) {
  106.         status = FS_FILE_REMOVED;
  107.     }
  108.     if ((status != SUCCESS) && (status != FS_FILE_REMOVED)) {
  109.         printf( 
  110.         "Fsio_LocalFileHandleInit: Fsdm_FileDescFetch of %d failed 0x%x\n",
  111.                 fileIDPtr->minor, status);
  112.     }
  113.     } 
  114.     if ((status == SUCCESS) && !(descPtr->flags & FSDM_FD_ALLOC)) {
  115.     status = FS_FILE_REMOVED;
  116.     }
  117.     if (status == SUCCESS) { 
  118.     Fscache_Attributes attr;
  119.  
  120.     handlePtr->descPtr = descPtr;
  121.     handlePtr->flags = 0;
  122.     /*
  123.      * The use counts are updated when an I/O stream is opened on the file
  124.      */
  125.     handlePtr->use.ref = 0;
  126.     handlePtr->use.write = 0;
  127.     handlePtr->use.exec = 0;
  128.  
  129.     /*
  130.      * Copy attributes that are cached in the handle.
  131.      */
  132.     attr.firstByte = descPtr->firstByte;
  133.     attr.lastByte = descPtr->lastByte;
  134.     attr.accessTime = descPtr->accessTime;
  135.     attr.createTime = descPtr->createTime;
  136.     attr.modifyTime = descPtr->dataModifyTime;
  137.     attr.userType = descPtr->userType;
  138.     attr.permissions = descPtr->permissions;
  139.     attr.uid = descPtr->uid;
  140.     attr.gid = descPtr->gid;
  141.  
  142.     Fscache_FileInfoInit(&handlePtr->cacheInfo, 
  143.         (Fs_HandleHeader *)handlePtr,
  144.         descPtr->version, TRUE, &attr, domainPtr->backendPtr);
  145.  
  146.     Fsconsist_Init(&handlePtr->consist, (Fs_HandleHeader *)handlePtr);
  147.     Fsio_LockInit(&handlePtr->lock);
  148.     Fscache_ReadAheadInit(&handlePtr->readAhead);
  149.  
  150.     handlePtr->segPtr = (Vm_Segment *)NIL;
  151.     }
  152.     if (status != SUCCESS) {
  153.     Fsutil_HandleRelease(handlePtr, FALSE);
  154.     Fsutil_HandleRemove(handlePtr);
  155.     if (allocated) {
  156.         free((Address)descPtr);
  157.      }
  158.     *newHandlePtrPtr = (Fsio_FileIOHandle *)NIL;
  159.     } else {
  160.     if (descPtr->fileType == FS_DIRECTORY) {
  161.         fs_Stats.object.directory++;
  162.     } else {
  163.         fs_Stats.object.files++;
  164.     }
  165.     *newHandlePtrPtr = handlePtr;
  166.     }
  167.     Fsdm_DomainRelease(fileIDPtr->major);
  168.     return(status);
  169. }
  170.  
  171. /*
  172.  *----------------------------------------------------------------------
  173.  *
  174.  * Fsio_FileSyncLockCleanup --
  175.  *
  176.  *    This takes care of the dynamically allocated Sync_Lock's that
  177.  *    are embedded in a Fsio_FileIOHandle.  This routine is
  178.  *    called when the file handle is being removed.
  179.  *
  180.  * Results:
  181.  *    None.
  182.  *
  183.  * Side effects:
  184.  *    The locking statistics for this handle are combined with the
  185.  *    summary statistics for the lock types in the handle
  186.  *
  187.  *----------------------------------------------------------------------
  188.  */
  189. void
  190. Fsio_FileSyncLockCleanup(handlePtr)
  191.     Fsio_FileIOHandle *handlePtr;
  192. {
  193.     Fsconsist_SyncLockCleanup(&handlePtr->consist);
  194.     Fscache_InfoSyncLockCleanup(&handlePtr->cacheInfo);
  195.     Fscache_ReadAheadSyncLockCleanup(&handlePtr->readAhead);
  196. }
  197.  
  198. /*
  199.  *----------------------------------------------------------------------
  200.  *
  201.  * Fsio_FileNameOpen --
  202.  *
  203.  *    This is called in two cases after name lookup on the server.
  204.  *    The first is when a client is opening the file from Fs_Open.
  205.  *    The second is when a lookup is done when getting/setting the
  206.  *    attributes of the files.  In the open case this routine has
  207.  *    to set up Fsio_FileState that the client will use to complete
  208.  *    the setup of its stream, and create a server-side stream.
  209.  *    The handle should be locked upon entry, it remains locked upon return.
  210.  *
  211.  * Results:
  212.  *    SUCCESS.
  213.  *
  214.  * Side effects:
  215.  *    The major side effect of this routine is to invoke cache consistency
  216.  *    actions by other clients.  This also does conflict checking, like
  217.  *    preventing writing if a file is being executed.  Lastly, a shadow
  218.  *    stream is created here on the server to support migration.
  219.  *
  220.  *----------------------------------------------------------------------
  221.  */
  222. ReturnStatus
  223. Fsio_FileNameOpen(handlePtr, openArgsPtr, openResultsPtr)
  224.      register Fsio_FileIOHandle *handlePtr;    /* A handle from FslclLookup.
  225.                      * Should be LOCKED upon entry,
  226.                      * Returned UNLOCKED. */
  227.     Fs_OpenArgs        *openArgsPtr;    /* Standard open arguments */
  228.     Fs_OpenResults    *openResultsPtr;/* For returning ioFileID, streamID,
  229.                      * and Fsio_FileState */
  230. {
  231.     Fsio_FileState *fileStatePtr;
  232.     ReturnStatus status;
  233.     register useFlags = openArgsPtr->useFlags;
  234.     register clientID = openArgsPtr->clientID;
  235.     register Fs_Stream *streamPtr;
  236.  
  237.     if ((useFlags & FS_WRITE) &&
  238.     (handlePtr->descPtr->fileType == FS_DIRECTORY)) {
  239.     status = FS_IS_DIRECTORY;
  240.     goto exit;
  241.     }
  242.     if (handlePtr->descPtr->fileType == FS_DIRECTORY) {
  243.     /*
  244.      * Strip off execute permission that was used to allow access to
  245.      * a directory.
  246.      */
  247.     useFlags &= ~FS_EXECUTE;
  248.     }
  249.     /*
  250.      * Check against writing and executing at the same time.  Fs_Open already
  251.      * checks that useFlags doesn't contain both execute and write bits.
  252.      */
  253.     if (((useFlags & FS_EXECUTE) && (handlePtr->use.write > 0)) ||
  254.     ((useFlags & (FS_WRITE|FS_CREATE)) && (handlePtr->use.exec > 0))) {
  255.     status = FS_FILE_BUSY;
  256.     goto exit;
  257.     }
  258.     /*
  259.      * Add in read permission when executing a file so Fs_Read doesn't
  260.      * foil page-ins later.
  261.      */
  262.     if ((useFlags & FS_EXECUTE) && (handlePtr->descPtr->fileType == FS_FILE)) {
  263.     useFlags |= FS_READ;
  264.     }
  265.     /*
  266.      * Set up the ioFileIDPtr so our caller can set/get attributes.
  267.      */
  268.     openResultsPtr->ioFileID = handlePtr->hdr.fileID;
  269.     if (clientID != rpc_SpriteID) {
  270.     openResultsPtr->ioFileID.type = FSIO_RMT_FILE_STREAM;
  271.     }
  272.     if (useFlags == 0) { 
  273.     /*
  274.      * Only being called from the get/set attributes code.
  275.      * Setting up the ioFileID is all that is needed.
  276.      */
  277.     status = SUCCESS;
  278.     } else {
  279.     /*
  280.      * Called during an open.  Update the summary use counts while
  281.      * we still have the handle locked.  Then unlock the handle and
  282.      * do consistency call-backs.  The handle is unlocked to allow
  283.      * servicing of RPCs which are side effects
  284.      * of the consistency requests (i.e. write-backs).
  285.      */
  286.     handlePtr->use.ref++;
  287.     if (useFlags & FS_WRITE) {
  288.         handlePtr->use.write++;
  289.         IncVersionNumber(handlePtr);
  290.     }
  291.     if (useFlags & FS_EXECUTE) {
  292.         handlePtr->use.exec++;
  293.     }
  294.     Fsutil_HandleUnlock(handlePtr);
  295.     fileStatePtr = mnew(Fsio_FileState);
  296.     status = Fsconsist_FileConsistency(handlePtr, clientID, useFlags,
  297.             &fileStatePtr->cacheable, &fileStatePtr->openTimeStamp);
  298.     if (status == SUCCESS) {
  299.         /*
  300.          * Copy cached attributes into the returned file state.
  301.          */
  302.         Fscache_GetCachedAttr(&handlePtr->cacheInfo, &fileStatePtr->version,
  303.             &fileStatePtr->attr);
  304.         /*
  305.          * Return new usage flags to the client.  This lets us strip
  306.          * off the execute use flag (above, for directories) so
  307.          * the client doesn't have to worry about it.
  308.          */
  309.         fileStatePtr->newUseFlags = useFlags;
  310.         openResultsPtr->streamData = (ClientData)fileStatePtr;
  311.         openResultsPtr->dataSize = sizeof(Fsio_FileState);
  312.  
  313.         if (handlePtr->descPtr->fileType == FS_DIRECTORY) {
  314.         fileStatePtr->newUseFlags |= FS_DIR;
  315.         }
  316.  
  317.         /*
  318.          * Now set up a shadow stream on here on the server so we
  319.          * can support shared offset even after migration.
  320.          * Note: prefix handles get opened, but the stream is not used,
  321.          * could dispose stream in FslclExport.
  322.          */
  323.  
  324.         streamPtr = Fsio_StreamCreate(rpc_SpriteID, clientID,
  325.         (Fs_HandleHeader *)handlePtr, useFlags, handlePtr->hdr.name);
  326.         openResultsPtr->streamID = streamPtr->hdr.fileID;
  327.  
  328.         /*
  329.          * Handles should be put into recovery box if 1) we're the server
  330.          * for the object, and 2) either it's a remote request or we're
  331.          * sharing the object with a client.  XXX Right now I don't have
  332.          * the sharing stuff in here!!! XXX
  333.          */
  334.         if (recov_Transparent && clientID != rpc_SpriteID) {
  335.         /* Add file handle to recov box. */
  336.         status = Fsrecov_AddHandle((Fs_HandleHeader *) handlePtr,
  337.             (Fs_FileID *) NIL, clientID,
  338.             useFlags, fileStatePtr->cacheable, TRUE);
  339.         /* We'll have to do better than this! */
  340.         if (status != SUCCESS) {
  341.             panic(
  342.             "Fsio_FileNameOpen: couldn't add handle to recov box.");
  343.         }
  344.         /*
  345.          * Now add mapping between stream and ioHandle.  We'll need to
  346.          * handle error cases better!!
  347.          */
  348.         status = Fsrecov_AddHandle((Fs_HandleHeader *) streamPtr,
  349.             (Fs_FileID *) &((Fs_HandleHeader *) handlePtr)->fileID,
  350.             clientID, streamPtr->flags, streamPtr->offset, TRUE);
  351.         if (status != SUCCESS) {
  352.             panic(
  353.             "Fsio_FileNameOpen: couldn't add stream to recov box.");
  354.         }
  355.         }
  356.         Fsutil_HandleRelease(streamPtr, TRUE);
  357.         return(SUCCESS);
  358.     } else {
  359.         /*
  360.          * Consistency call-backs failed because the last writer
  361.          * could not write back its copy of the file. We garbage
  362.          * collect the client to retreat to a known bookkeeping point.
  363.          */
  364.         int ref, write, exec;
  365.         printf("Consistency failed %x on <%d,%d>\n", status,
  366.         handlePtr->hdr.fileID.major, handlePtr->hdr.fileID.minor);
  367.         Fsutil_HandleLock(handlePtr);
  368.         Fsconsist_Kill(&handlePtr->consist, clientID,
  369.               &ref, &write, &exec);
  370.         handlePtr->use.ref   -= ref;
  371.         handlePtr->use.write -= write;
  372.         handlePtr->use.exec  -= exec;
  373.         if ((handlePtr->use.ref < 0) || (handlePtr->use.write < 0) ||
  374.             (handlePtr->use.exec < 0)) {
  375.         panic("Fsio_FileNameOpen: client %d ref %d write %d exec %d\n",
  376.             clientID, handlePtr->use.ref,
  377.             handlePtr->use.write, handlePtr->use.exec);
  378.         }
  379.         free((Address)fileStatePtr);
  380.     }
  381.     }
  382. exit:
  383.     Fsutil_HandleUnlock(handlePtr);
  384.     return(status);
  385. }
  386.  
  387. /*
  388.  *----------------------------------------------------------------------
  389.  *
  390.  * Fsio_FileReopen --
  391.  *
  392.  *      Reopen a file for use by a remote client. State is maintained in the
  393.  *      handle's client list about this open and whether or not the client
  394.  *      is caching.
  395.  *
  396.  * Results:
  397.  *    A failure code if the client was caching dirty blocks but lost
  398.  *    the race to re-open its file.  (i.e. another client already opened
  399.  *    for writing.)
  400.  *
  401.  * Side effects:
  402.  *    The client use state for the client is brought into agreement
  403.  *    with what the client tells us.  We do cache consistency too.
  404.  *    
  405.  *
  406.  *----------------------------------------------------------------------
  407.  */
  408. /*ARGSUSED*/
  409. ReturnStatus
  410. Fsio_FileReopen(hdrPtr, clientID, inData, outSizePtr, outDataPtr)
  411.     Fs_HandleHeader    *hdrPtr;    /* IGNORED here on the server */
  412.     int            clientID;    /* Client doing the reopen */
  413.     ClientData        inData;        /* Fsio_FileReopenParams */
  414.     int            *outSizePtr;    /* Size of returned data */
  415.     ClientData        *outDataPtr;    /* Returned data */
  416. {
  417.     register Fsio_FileReopenParams *reopenParamsPtr; /* Parameters from RPC */
  418.     register Fsio_FileState    *fileStatePtr;    /* Results for RPC */
  419.     Fsio_FileIOHandle            *handlePtr;    /* Local handle for file */
  420.     register ReturnStatus    status = SUCCESS; /* General return code */
  421.     Fsdm_Domain            *domainPtr;
  422.     Fsrecov_HandleState        recovInfo;
  423.  
  424.     *outDataPtr = (ClientData) NIL;
  425.     *outSizePtr = 0;
  426.     /*
  427.      * Do initial setup for the reopen.  We make sure that the disk
  428.      * for the file is still around first, mark the client
  429.      * as doing recovery, and fetch a local handle for the file.
  430.      * NAME note: we have no name for the file after a re-open.
  431.      */
  432.     reopenParamsPtr = (Fsio_FileReopenParams *) inData;
  433.  
  434.     /*
  435.      * If this is a fast restart, but we're still doing recovery
  436.      * (fsrecov_FromBox is FALSE), we can look at recov box contents and
  437.      * check them against what the client says is true.
  438.      */
  439.     if (recov_Transparent && fsrecov_AlreadyInit) {
  440.         Fs_FileID       fid;
  441.  
  442.     /*
  443.      * The object won't be in the box if it has a 0 ref count and no
  444.      * dirty blocks.  It is
  445.      * a bug currently that clients can send reopen requests for files
  446.      * that aren't open (0 ref count), but for which they have cached
  447.      * blocks.  We'll fix this soon, I hope.
  448.      */
  449.     if (reopenParamsPtr->use.ref <= 0 &&
  450.         !(reopenParamsPtr->flags & FSIO_HAVE_BLOCKS)) {
  451.         goto FixClientBug;
  452.     }
  453.         fid = reopenParamsPtr->fileID;
  454.         /* Get info from recov box. */
  455.         status = Fsrecov_GetHandle(fid, clientID, &recovInfo, TRUE);
  456.         if (status != SUCCESS) {
  457.             panic("Fsio_FileReopen: couldn't get recov info for handle.");
  458.         }
  459.         /* Test it for sameness. */
  460.         if ((recovInfo.fileID.major != reopenParamsPtr->fileID.major) ||
  461.                 (recovInfo.fileID.minor != reopenParamsPtr->fileID.minor)) {
  462.             panic("Fsio_FileReopen: major or minor numbers disagree.");
  463.         }
  464.         if (recovInfo.use.ref != reopenParamsPtr->use.ref) {
  465.             panic("Fsio_FileReopen: refs disagree.");
  466.         }
  467.         if (recovInfo.use.write != reopenParamsPtr->use.write) {
  468.             panic("Fsio_FileReopen: write refs disagree.");
  469.         }
  470.         if (recovInfo.use.exec != reopenParamsPtr->use.exec) {
  471.             panic("Fsio_FileReopen: exec refs disagree.");
  472.         }
  473.         if (recovInfo.info != reopenParamsPtr->version) {
  474.             panic("Fsio_FileReopen: versions disagree.");
  475.         }
  476.     /*
  477.      * If we're doing recovery from the box, then return what we
  478.      * recovered from the box to the client that still is doing reopens.
  479.      */
  480.     if (fsrecov_FromBox) {
  481.         handlePtr = (Fsio_FileIOHandle *) Fsutil_HandleFetch(&fid);
  482.         fileStatePtr = mnew(Fsio_FileState);
  483.         fileStatePtr->cacheable = reopenParamsPtr->flags & FSIO_HAVE_BLOCKS;
  484.         fileStatePtr->version = recovInfo.info;
  485.         fileStatePtr->attr = handlePtr->cacheInfo.attr;
  486.         fileStatePtr->newUseFlags = 0;    /* Not used in re-open */
  487.         *outDataPtr = (ClientData) fileStatePtr;
  488.         *outSizePtr = sizeof(Fsio_FileState);
  489.         Fsutil_HandleRelease(handlePtr, TRUE);
  490.  
  491.         return SUCCESS;
  492.     }
  493.     }
  494.  
  495. /*
  496.  * If a client reopens a file with a 0 ref count, we make the reopen jump
  497.  * here regardless of whether we're recovering from the recovery box
  498.  * or not.  The problem is that if the ref count is 0, we won't find the
  499.  * object in the box!  We'll fix the client side soon to prevent this.
  500.  */
  501. FixClientBug:
  502.     domainPtr = Fsdm_DomainFetch(reopenParamsPtr->fileID.major, FALSE);
  503.     if (domainPtr == (Fsdm_Domain *)NIL) {
  504.     return(FS_DOMAIN_UNAVAILABLE);
  505.     }
  506.     status = Fsio_LocalFileHandleInit(&reopenParamsPtr->fileID, (char *)NIL,
  507.     (Fsdm_FileDescriptor *) NIL, FALSE, &handlePtr);
  508.     if (status != SUCCESS) {
  509.     goto reopenReturn;
  510.     }
  511.     /*
  512.      * See if the client can still cache its dirty blocks.
  513.      */
  514.     if (reopenParamsPtr->flags & FSIO_HAVE_BLOCKS) {
  515.     status = Fscache_CheckVersion(&handlePtr->cacheInfo,
  516.                      reopenParamsPtr->version, clientID);
  517.     if (status != SUCCESS) {
  518.         Fsutil_HandleRelease(handlePtr, TRUE);
  519.         goto reopenReturn;
  520.     }
  521.     }
  522.     /*
  523.      * Update global use counts and version number.
  524.      */
  525.     Fsconsist_ReopenClient(handlePtr, clientID, reopenParamsPtr->use,
  526.             reopenParamsPtr->flags & FSIO_HAVE_BLOCKS);
  527.     if (reopenParamsPtr->use.write > 0) {
  528.     IncVersionNumber(handlePtr);
  529.     }
  530.     /*
  531.      * Now unlock the handle and do cache consistency call-backs.
  532.      */
  533.     fileStatePtr = mnew(Fsio_FileState);
  534.     fileStatePtr->cacheable = reopenParamsPtr->flags & FSIO_HAVE_BLOCKS;
  535.     Fsutil_HandleUnlock(handlePtr);
  536.     status = Fsconsist_ReopenConsistency(handlePtr, clientID, reopenParamsPtr->use,
  537.         reopenParamsPtr->flags & FS_SWAP,
  538.         &fileStatePtr->cacheable, &fileStatePtr->openTimeStamp);
  539.     if (status != SUCCESS) {
  540.     /*
  541.      * Consistency call-backs failed, probably due to disk-full.
  542.      * We kill the client here as it will invalidate its handle
  543.      * after this re-open fails.
  544.      */
  545.     int ref, write, exec;
  546.     Fsutil_HandleLock(handlePtr);
  547.     Fsconsist_Kill(&handlePtr->consist, clientID, &ref, &write, &exec);
  548.     handlePtr->use.ref   -= ref;
  549.     handlePtr->use.write -= write;
  550.     handlePtr->use.exec  -= exec;
  551.     if ((handlePtr->use.ref < 0) || (handlePtr->use.write < 0) ||
  552.         (handlePtr->use.exec < 0)) {
  553.         panic("Fsio_FileReopen: client %d ref %d write %d exec %d\n",
  554.         clientID, handlePtr->use.ref,
  555.         handlePtr->use.write, handlePtr->use.exec);
  556.     }
  557.     Fsutil_HandleUnlock(handlePtr);
  558.     free((Address)fileStatePtr);
  559.     } else {
  560.     /*
  561.      * Successful re-open here on the server. Copy cached attributes
  562.      * into the returned file state.
  563.      */
  564.     Fscache_GetCachedAttr(&handlePtr->cacheInfo, &fileStatePtr->version,
  565.             &fileStatePtr->attr);
  566.     fileStatePtr->newUseFlags = 0;        /* Not used in re-open */
  567.     *outDataPtr = (ClientData) fileStatePtr;
  568.     *outSizePtr = sizeof(Fsio_FileState);
  569.  
  570.         if (recov_Transparent && !fsrecov_AlreadyInit &&
  571.         (reopenParamsPtr->use.ref > 0 ||
  572.         (reopenParamsPtr->flags & FSIO_HAVE_BLOCKS))) {
  573.             int         useFlags = 0;
  574.             Fs_FileID   fid;
  575.  
  576.             fid = reopenParamsPtr->fileID;
  577.             if (handlePtr->use.write) {
  578.                 useFlags |= FS_WRITE;
  579.             }
  580.             if (handlePtr->use.exec) {
  581.                 useFlags |= FS_EXECUTE;
  582.             }
  583.             /* Add file handle to recov box. */
  584.             status = Fsrecov_AddHandle((Fs_HandleHeader *) handlePtr,
  585.             (Fs_FileID *) NIL, clientID, useFlags,
  586.             fileStatePtr->cacheable, (reopenParamsPtr->use.ref > 0));
  587.             /* We'll have to do better than this! */
  588.             if (status != SUCCESS) {
  589.                 panic("Fsio_FileReopen: couldn't add handle to recov box.");
  590.             }
  591.         /* Stream is added in stream reopen procedure. */
  592.         }
  593.     }
  594.     Fsutil_HandleRelease(handlePtr, FALSE);
  595. reopenReturn:
  596.     Fsdm_DomainRelease(reopenParamsPtr->fileID.major);
  597.     return(status);
  598. }
  599.  
  600. /*
  601.  *----------------------------------------------------------------------
  602.  *
  603.  * Fsio_FileIoOpen --
  604.  *
  605.  *      Set up a stream for a local disk file.  This is called from Fs_Open to
  606.  *    complete the opening of a stream.  By this time any cache consistency
  607.  *    actions have already been taken, and local use counts have been
  608.  *    incremented by Fsio_FileNameOpen.
  609.  *
  610.  * Results:
  611.  *    SUCCESS, unless there was an error installing the handle.
  612.  *
  613.  * Side effects:
  614.  *    Installs the handle for the file.  This increments its refererence
  615.  *    count (different than the use count).
  616.  *
  617.  *----------------------------------------------------------------------
  618.  */
  619. /*ARGSUSED*/
  620. ReturnStatus
  621. Fsio_FileIoOpen(ioFileIDPtr, flagsPtr, clientID, streamData, name, ioHandlePtrPtr)
  622.     Fs_FileID        *ioFileIDPtr;    /* I/O fileID from the name server */
  623.     int            *flagsPtr;    /* Return only.  The server returns
  624.                      * a modified useFlags in Fsio_FileState */
  625.     int            clientID;    /* IGNORED */
  626.     ClientData        streamData;    /* Fsio_FileState. */
  627.     char        *name;        /* File name for error msgs */
  628.     Fs_HandleHeader    **ioHandlePtrPtr;/* Return - a handle set up for
  629.                      * I/O to a file, NIL if failure. */
  630. {
  631.     register ReturnStatus    status;
  632.  
  633.     status = Fsio_LocalFileHandleInit(ioFileIDPtr, name, 
  634.         (Fsdm_FileDescriptor *) NIL, FALSE, 
  635.         (Fsio_FileIOHandle **)ioHandlePtrPtr);
  636.     if (status == SUCCESS) {
  637.     /*
  638.      * Return the new useFlags from the server.  It has stripped off
  639.      * execute permission for directories.
  640.      */
  641.     *flagsPtr = ( (Fsio_FileState *)streamData )->newUseFlags;
  642.     Fsutil_HandleUnlock(*ioHandlePtrPtr);
  643.     }
  644.     free((Address)streamData);
  645.     return(status);
  646. }
  647.  
  648. /*
  649.  *----------------------------------------------------------------------
  650.  *
  651.  * Fsio_FileClose --
  652.  *
  653.  *    Close time processing for local files.  We need to remove ourselves
  654.  *    from the list of clients of the file, decrement use counts, and
  655.  *    handle pending deletes.  This returns either with one reference
  656.  *    to the handle released, or with the handle removed entirely.
  657.  *
  658.  * Results:
  659.  *    SUCCESS, FS_FILE_REMOVED, or an error code from the disk operation
  660.  *    on the file descriptor.
  661.  *
  662.  * Side effects:
  663.  *    Attributes cached on clients are propogated to the local handle.
  664.  *    Use counts in the client list are decremented.  The handle's
  665.  *    use counts are decremented.  If the file has been deleted, then
  666.  *    the file descriptor is so marked, other clients are told of
  667.  *    the delete, and the handle is removed entirely.  Otherwise,
  668.  *    a reference on the handle is released.
  669.  *
  670.  *----------------------------------------------------------------------
  671.  */
  672.  
  673. ReturnStatus
  674. Fsio_FileClose(streamPtr, clientID, procID, flags, dataSize, closeData)
  675.     Fs_Stream        *streamPtr;    /* Stream to regular file */
  676.     int            clientID;    /* Host ID of closer */
  677.     Proc_PID        procID;        /* Process ID of closer */
  678.     int            flags;        /* Flags from the stream being closed */
  679.     int            dataSize;    /* Size of closeData */
  680.     ClientData        closeData;    /* Ref. to Fscache_Attributes */
  681. {
  682.     register Fsio_FileIOHandle *handlePtr =
  683.         (Fsio_FileIOHandle *)streamPtr->ioHandlePtr;
  684.     ReturnStatus        status;
  685.     Boolean            wasCached = TRUE;
  686.  
  687.     /*
  688.      * Update the client state to reflect the close by the client.
  689.      */
  690.  
  691.     /*
  692.      * This code is to track down a problem with clients sending bad
  693.      * data.
  694.      */
  695.     if (flags & FS_EXECUTE) {
  696.     List_Links *clientList = &(handlePtr->consist.clientList);
  697.     Fsconsist_ClientInfo *clientPtr;
  698.     LIST_FORALL(clientList, (List_Links *)clientPtr) {
  699.         if (clientPtr->clientID == clientID) {
  700.            if (clientPtr->use.exec==0) {
  701.            printf("***ERROR***:Client %d: bad close on %s\n",
  702.                clientID, Fsutil_HandleName(handlePtr));
  703.           return(FAILURE);
  704.            }
  705.         }
  706.         }
  707.     }
  708.     if (!Fsconsist_Close(&handlePtr->consist, clientID, flags, &wasCached)) {
  709.     printf("Fsio_FileClose, client %d pid %x unknown for file <%d,%d>\n",
  710.           clientID, procID, handlePtr->hdr.fileID.major,
  711.           handlePtr->hdr.fileID.minor);
  712.     Fsutil_HandleUnlock(handlePtr);
  713.     return(FS_STALE_HANDLE);
  714.     }
  715.     if (wasCached && dataSize != 0) {
  716.     /*
  717.      * Update the server's attributes from ones cached on the client.
  718.      */
  719.     Fscache_UpdateAttrFromClient(clientID, &handlePtr->cacheInfo,
  720.                 (Fscache_Attributes *)closeData);
  721.     (void)Fsdm_UpdateDescAttr(handlePtr, &handlePtr->cacheInfo.attr, -1);
  722.     }
  723.  
  724.     Fsio_LockClose(&handlePtr->lock, &streamPtr->hdr.fileID);
  725.  
  726.     /*
  727.      * Update use counts and handle pending deletions.
  728.      */
  729.     status = Fsio_FileCloseInt(handlePtr, 1, (flags & FS_WRITE) != 0,
  730.                      (flags & FS_EXECUTE) != 0,
  731.                      clientID, TRUE);
  732.     if (status == FS_FILE_REMOVED) {
  733.     /* XXX What is this about? XXX */
  734.     if (recov_Transparent && clientID != rpc_SpriteID) {
  735.         status = SUCCESS;
  736.             if (Fsrecov_DeleteHandle((Fs_HandleHeader *) handlePtr, clientID,
  737.                     flags) != SUCCESS) {
  738.                 /* We'll have to do better than this! */
  739.                 panic("Fsio_FileClose: couldn't remove handle from recov box.");
  740.             }
  741.             if (Fsrecov_DeleteHandle((Fs_HandleHeader *) streamPtr, clientID,
  742.                     streamPtr->flags) != SUCCESS) {
  743.                 /* We'll have to do better than this! */
  744.                 panic("Fsio_FileClose: couldn't remove stream from recov box.");
  745.             }
  746.     }
  747.     } else {
  748.     status = SUCCESS;
  749.     if (recov_Transparent && clientID != rpc_SpriteID) {
  750.         if (Fsrecov_DeleteHandle((Fs_HandleHeader *) handlePtr, clientID,
  751.             flags) != SUCCESS) {
  752.         /* We'll have to do better than this! */
  753.         panic("Fsio_FileClose: couldn't remove handle from recov box.");
  754.         }
  755.         if (Fsrecov_DeleteHandle((Fs_HandleHeader *) streamPtr, clientID,
  756.             streamPtr->flags) != SUCCESS) {
  757.         /* We'll have to do better than this! */
  758.         panic("Fsio_FileClose: couldn't remove stream from recov box.");
  759.         }
  760.         }
  761.     Fsutil_HandleRelease(handlePtr, TRUE);
  762.     }
  763.  
  764.     return(status);
  765. }
  766.  
  767. /*
  768.  * ----------------------------------------------------------------------------
  769.  *
  770.  * Fsio_FileCloseInt --
  771.  *
  772.  *    Close a file, handling pending deletions.
  773.  *    This is called from the regular close routine, from
  774.  *    the file client-kill cleanup routine, and from the
  775.  *    lookup routine that deletes file names.
  776.  *
  777.  * Results:
  778.  *    SUCCESS or FS_FILE_REMOVED.
  779.  *
  780.  * Side effects:
  781.  *    Adjusts use counts and does pending deletions.  If the file is
  782.  *    deleted the handle can not be used anymore.  Otherwise it
  783.  *    is left locked.
  784.  *
  785.  * ----------------------------------------------------------------------------
  786.  *
  787.  */
  788. ReturnStatus
  789. Fsio_FileCloseInt(handlePtr, ref, write, exec, clientID, callback)
  790.     Fsio_FileIOHandle *handlePtr;    /* File to clean up */
  791.     int ref;                /* Number of uses to remove */
  792.     int write;                /* Number of writers to remove */
  793.     int exec;                /* Number of executers to remove */
  794.     int clientID;            /* Closing, or crashed, client */
  795.     Boolean callback;            /* TRUE if we should call back to
  796.                      * the client and tell it about
  797.                      * the deletion. */
  798. {
  799.     register ReturnStatus status;
  800.     /*
  801.      * Update the global/summary use counts for the file.
  802.      */
  803.     handlePtr->use.ref -= ref;
  804.     handlePtr->use.write -= write;
  805.     handlePtr->use.exec -= exec;
  806.     if (handlePtr->use.ref < 0 || handlePtr->use.write < 0 ||
  807.     handlePtr->use.exec < 0) {
  808.     panic("Fsio_FileCloseInt <%d,%d> use %d, write %d, exec %d\n",
  809.         handlePtr->hdr.fileID.major, handlePtr->hdr.fileID.minor,
  810.         handlePtr->use.ref, handlePtr->use.write, handlePtr->use.exec);
  811.     }
  812.  
  813.     /*
  814.      * Handle pending deletes
  815.      *    0. Make sure it isn't being deleted already.
  816.      *    1. Scan the client list and call-back to the last writer if
  817.      *        it is not the client doing the close.  The handle gets
  818.      *        temporarily unlocked during the callback, so we are
  819.      *        are careful to ensure only one process does the delete.
  820.      *    2. Mark the disk descriptor as deleted,
  821.      *    3. Remove the file handle.
  822.      *    4. Return FS_FILE_REMOVED so clients know to nuke their cache.
  823.      */
  824.     if ((handlePtr->use.ref == 0) &&
  825.     (handlePtr->flags & FSIO_FILE_NAME_DELETED)) {
  826.     if ((handlePtr->flags & FSIO_FILE_DESC_DELETED) == 0) {
  827.         handlePtr->flags |= FSIO_FILE_DESC_DELETED;
  828.         if (handlePtr->descPtr->fileType == FS_DIRECTORY) {
  829.         fs_Stats.object.directory--;
  830.         } else {
  831.         fs_Stats.object.files--;
  832.         }
  833.         if (callback) {
  834.         Fsconsist_ClientRemoveCallback(&handlePtr->consist, clientID);
  835.         }
  836.         (void)Fslcl_DeleteFileDesc(handlePtr);
  837.         Fsio_FileSyncLockCleanup(handlePtr);
  838.         if (callback) {
  839.         Fsutil_HandleRelease(handlePtr, FALSE);
  840.         }
  841.         Fsutil_HandleRemove(handlePtr);
  842.     } else {
  843.         /*
  844.          * The following printf is a mousetrap to verify that the 
  845.          * bug where Proc_ServerProcs leave files locked was fixed.
  846.          * Remove it once we are positive the bug is fixed. JHH 11/5/90
  847.          */
  848.         printf(
  849.     "Fsio_FileCloseInt: almost returned FS_FILE_REMOVED w/ handle locked\n");
  850.         Fsutil_HandleUnlock(handlePtr);
  851.     }
  852.     status = FS_FILE_REMOVED;
  853.     } else {
  854.     status = SUCCESS;
  855.     }
  856.     return(status);
  857. }
  858.  
  859. /*
  860.  * ----------------------------------------------------------------------------
  861.  *
  862.  * Fsio_FileClientKill --
  863.  *
  864.  *    Called when a client is assumed down.  This cleans up the
  865.  *    cache consistency state associated with the client, and reflects
  866.  *    these changes in uses (i.e. less writers) in the handle's global
  867.  *    use counts.
  868.  *    
  869.  *
  870.  * Results:
  871.  *    SUCCESS.
  872.  *
  873.  * Side effects:
  874.  *    Removes the client list entry for the client and adjusts the
  875.  *    use counts on the file.  This has to remove or unlock the handle.
  876.  *
  877.  * ----------------------------------------------------------------------------
  878.  *
  879.  */
  880. void
  881. Fsio_FileClientKill(hdrPtr, clientID)
  882.     Fs_HandleHeader    *hdrPtr;    /* File to clean up */
  883.     int            clientID;    /* Host assumed down */
  884. {
  885.     Fsio_FileIOHandle *handlePtr = (Fsio_FileIOHandle *)hdrPtr;
  886.     int refs, writes, execs;
  887.     register ReturnStatus status;
  888.     int    flags = FS_READ;
  889.  
  890.     Fsconsist_IOClientKill(&handlePtr->consist.clientList, clientID,
  891.             &refs, &writes, &execs);
  892.     Fsio_LockClientKill(&handlePtr->lock, clientID);
  893.  
  894.     status = Fsio_FileCloseInt(handlePtr, refs, writes, execs, clientID, FALSE);
  895.     while (refs > 0) {
  896.         if (writes > 0) {
  897.             flags |= FS_WRITE;
  898.         }
  899.         if (execs > 0) {
  900.             flags |= FS_EXECUTE;
  901.         }
  902.     if (recov_Transparent && clientID != rpc_SpriteID) {
  903.         if (Fsrecov_DeleteHandle((Fs_HandleHeader *) handlePtr, clientID,
  904.             flags) != SUCCESS) {
  905.         /* We'll have to do better than this! */
  906.         panic("Fsio_FileClientKill: couldn't remove handle from recov box.");
  907.         }
  908.         }
  909.         refs--;
  910.         if (writes > 0) {
  911.             writes--;
  912.         }
  913.         if (execs > 0) {
  914.             execs--;
  915.         }
  916.         flags = FS_READ;
  917.     }
  918.     if (status != FS_FILE_REMOVED) {
  919.     Fsutil_HandleUnlock(handlePtr);
  920.     }
  921. }
  922.  
  923. /*
  924.  * ----------------------------------------------------------------------------
  925.  *
  926.  * Fsio_FileScavenge --
  927.  *
  928.  *    Called periodically to see if this handle is still needed.
  929.  *    
  930.  *
  931.  * Results:
  932.  *    TRUE if it removed the handle.
  933.  *
  934.  * Side effects:
  935.  *    Removes the handle if their are no references to it and no
  936.  *    blocks in the cache for it.  Otherwise it unlocks the handle
  937.  *    before returning.
  938.  *
  939.  * ----------------------------------------------------------------------------
  940.  *
  941.  */
  942. /*ARGSUSED*/
  943. Boolean
  944. Fsio_FileScavenge(hdrPtr)
  945.     Fs_HandleHeader    *hdrPtr;    /* File to clean up */
  946. {
  947.     register Fsio_FileIOHandle *handlePtr = (Fsio_FileIOHandle *)hdrPtr;
  948.     register Boolean noUsers;
  949.  
  950.     /*
  951.      * We can reclaim the handle if the following holds.
  952.      *  0. The descriptor is not dirty.
  953.      *    1. There are no active users of the file.
  954.      *  2. The file is not undergoing deletion
  955.      *        (The deletion will remove the handle soon)
  956.      *  3. There are no remote clients of the file.  In particular,
  957.      *        the last writer might not be active, but we can't
  958.      *        nuke the handle until after it writes back.
  959.      */
  960.     noUsers = ((handlePtr->descPtr->flags & FSDM_FD_DIRTY) == 0) &&
  961.                (handlePtr->use.ref == 0) &&
  962.          ((handlePtr->flags & (FSIO_FILE_DESC_DELETED|
  963.                    FSIO_FILE_NAME_DELETED)) == 0) &&
  964.           (Fsconsist_NumClients(&handlePtr->consist) == 0);
  965.     if (noUsers && Fscache_OkToScavenge(&handlePtr->cacheInfo)) {
  966.     register Boolean isDir;
  967.     /*
  968.      * Remove handles for files with no users and no blocks in cache.
  969.      * We tell VM not to cache the segment associated with the file.
  970.      * The "attempt remove" call unlocks the handle and then frees its
  971.      * memory if there are no references to it lingering from the name
  972.      * hash table.
  973.      */
  974.     Vm_FileChanged(&handlePtr->segPtr);
  975.     isDir = (handlePtr->descPtr->fileType == FS_DIRECTORY);
  976.     if (Fsutil_HandleAttemptRemove(hdrPtr)) {
  977.         if (isDir) {
  978.         fs_Stats.object.directory--;
  979.         fs_Stats.object.dirFlushed++;
  980.         } else {
  981.         fs_Stats.object.files--;
  982.         }
  983.         return(TRUE);
  984.     } else {
  985.         return(FALSE);
  986.     }
  987.     } else {
  988.     Fsutil_HandleUnlock(hdrPtr);
  989.     return(FALSE);
  990.     }
  991. }
  992.  
  993. /*
  994.  * ----------------------------------------------------------------------------
  995.  *
  996.  * Fsio_FileMigClose --
  997.  *
  998.  *    Initiate migration of a FSIO_LCL_FILE_STREAM.  There is no extra
  999.  *    state needed than already put together by Fsio_EncapStream.  However,
  1000.  *    we do release a low-level reference on the handle which is
  1001.  *    re-obtained by FsFileDeencap.  Other than that, we leave the
  1002.  *    book-keeping alone, waiting to atomically switch references from
  1003.  *    one client to the other at de-encapsulation time.
  1004.  *    
  1005.  *
  1006.  * Results:
  1007.  *    SUCCESS.
  1008.  *
  1009.  * Side effects:
  1010.  *    Release a reference on the handle header.
  1011.  *
  1012.  * ----------------------------------------------------------------------------
  1013.  *
  1014.  */
  1015. /*ARGSUSED*/
  1016. ReturnStatus
  1017. Fsio_FileMigClose(hdrPtr, flags)
  1018.     Fs_HandleHeader *hdrPtr;    /* File being encapsulated */
  1019.     int flags;            /* Use flags from the stream */
  1020. {
  1021.     panic( "Fsio_FileMigClose called\n");
  1022.     Fsutil_HandleRelease(hdrPtr, FALSE);
  1023.     return(SUCCESS);
  1024. }
  1025.  
  1026.  
  1027. /*
  1028.  * ----------------------------------------------------------------------------
  1029.  *
  1030.  * Fsio_FileMigOpen --
  1031.  *
  1032.  *    Complete setup of a stream to a local file after migration to the
  1033.  *    file server.  Fsio_FileMigrate has done the work of shifting use
  1034.  *    counts at the stream and I/O handle level.  This routine has to
  1035.  *    increment the low level I/O handle reference count to reflect
  1036.  *    the existence of a new stream to the I/O handle.
  1037.  *
  1038.  * Results:
  1039.  *    SUCCESS or FS_FILE_NOT_FOUND if the I/O handle can't be set up.
  1040.  *
  1041.  * Side effects:
  1042.  *    Gains one reference to the I/O handle.  Frees the client data.
  1043.  *
  1044.  * ----------------------------------------------------------------------------
  1045.  *
  1046.  */
  1047. /*ARGSUSED*/
  1048. ReturnStatus
  1049. Fsio_FileMigOpen(migInfoPtr, size, data, hdrPtrPtr)
  1050.     Fsio_MigInfo    *migInfoPtr;    /* Migration state */
  1051.     int        size;        /* sizeof(Fsio_FileState), IGNORED */
  1052.     ClientData    data;        /* referenced to Fsio_FileState */
  1053.     Fs_HandleHeader **hdrPtrPtr;    /* Return - I/O handle for the file */
  1054. {
  1055.     register ReturnStatus status;
  1056.     register Fsio_FileIOHandle *handlePtr;
  1057.  
  1058.     handlePtr = Fsutil_HandleFetchType(Fsio_FileIOHandle,
  1059.         &migInfoPtr->ioFileID);
  1060.     if (handlePtr == (Fsio_FileIOHandle *)NIL) {
  1061.     printf("Fsio_FileMigOpen, file <%d,%d> from client %d not found\n",
  1062.         migInfoPtr->ioFileID.major, migInfoPtr->ioFileID.minor,
  1063.         migInfoPtr->srcClientID);
  1064.     status = FS_FILE_NOT_FOUND;
  1065.     } else {
  1066.     Fsutil_HandleUnlock(handlePtr);
  1067.     *hdrPtrPtr = (Fs_HandleHeader *)handlePtr;
  1068.     status = SUCCESS;
  1069.     }
  1070.     free((Address)data);
  1071.     return(status);
  1072. }
  1073.  
  1074. /*
  1075.  * ----------------------------------------------------------------------------
  1076.  *
  1077.  * Fsio_FileMigrate --
  1078.  *
  1079.  *    This takes care of transfering references from one client to the other.
  1080.  *    Three things are done:  cache consistency actions are taken to
  1081.  *    reflect the movement of the client, file state is set up for use
  1082.  *    on the client in the MigEnd procedure, and cross-network stream
  1083.  *    sharing is detected.  A useful side-effect of this routine is
  1084.  *    to properly set the type in the ioFileID, either FSIO_LCL_FILE_STREAM
  1085.  *    or FSIO_RMT_FILE_STREAM.  In the latter case FsrmtFileMigrate
  1086.  *    is called to do all the work.
  1087.  *
  1088.  * Results:
  1089.  *    An error status if the I/O handle can't be set-up or if there
  1090.  *    is a cache consistency failure.  Otherwise SUCCESS is returned,
  1091.  *    *flagsPtr may have the FS_RMT_SHARED bit set, and *sizePtr
  1092.  *    and *dataPtr are set to reference Fsio_FileState.
  1093.  *
  1094.  * Side effects:
  1095.  *    Sets the correct stream type on the ioFileID.
  1096.  *    Shifts client references from the srcClient to the destClient.
  1097.  *    Set up and return Fsio_FileState for use by the MigEnd routine.
  1098.  *
  1099.  * ----------------------------------------------------------------------------
  1100.  *
  1101.  */
  1102. /*ARGSUSED*/
  1103. ReturnStatus
  1104. Fsio_FileMigrate(migInfoPtr, dstClientID, flagsPtr, offsetPtr, sizePtr, dataPtr)
  1105.     Fsio_MigInfo    *migInfoPtr;    /* Migration state */
  1106.     int        dstClientID;    /* ID of target client */
  1107.     int        *flagsPtr;    /* In/Out Stream usage flags */
  1108.     int        *offsetPtr;    /* Return - correct stream offset */
  1109.     int        *sizePtr;    /* Return - sizeof(Fsio_FileState) */
  1110.     Address    *dataPtr;    /* Return - pointer to Fsio_FileState */
  1111. {
  1112.     register Fsio_FileIOHandle    *handlePtr;
  1113.     register Fsio_FileState        *fileStatePtr;
  1114.     register ReturnStatus        status;
  1115.     Boolean                closeSrcClient;
  1116.  
  1117.     if (migInfoPtr->ioFileID.serverID != rpc_SpriteID) {
  1118.     /*
  1119.      * The file was local, which is why we were called, but is now remote.
  1120.      */
  1121.     migInfoPtr->ioFileID.type = FSIO_RMT_FILE_STREAM;
  1122.     return(FsrmtFileMigrate(migInfoPtr, dstClientID, flagsPtr, offsetPtr,
  1123.         sizePtr, dataPtr));
  1124.     }
  1125.     migInfoPtr->ioFileID.type = FSIO_LCL_FILE_STREAM;
  1126.     handlePtr = Fsutil_HandleFetchType(Fsio_FileIOHandle, &migInfoPtr->ioFileID);
  1127.     if (handlePtr == (Fsio_FileIOHandle *)NIL) {
  1128.     panic("Fsio_FileMigrate, no I/O handle");
  1129.     status = FS_STALE_HANDLE;
  1130.     } else {
  1131.  
  1132.     /*
  1133.      * At the stream level, add the new client to the set of clients
  1134.      * for the stream, and check for any cross-network stream sharing.
  1135.      * We only close the orignial client if the stream is unshared,
  1136.      * i.e. there are no references left there.
  1137.      */
  1138.     Fsio_StreamMigClient(migInfoPtr, dstClientID,
  1139.         (Fs_HandleHeader *)handlePtr, &closeSrcClient);
  1140.  
  1141.     /*
  1142.      * Adjust use counts on the I/O handle to reflect any new sharing.
  1143.      */
  1144.     Fsio_MigrateUseCounts(migInfoPtr->flags, closeSrcClient,
  1145.                   &handlePtr->use);
  1146.  
  1147.     /*
  1148.      * Update the client list, and take any required cache consistency
  1149.      * actions. The handle returns unlocked from the consistency routine.
  1150.      */
  1151.     fileStatePtr = mnew(Fsio_FileState);
  1152.     Fsutil_HandleUnlock(handlePtr);
  1153.     status = Fsconsist_MigrateConsistency(handlePtr,
  1154.         migInfoPtr->srcClientID,
  1155.         dstClientID, migInfoPtr->flags, closeSrcClient,
  1156.         &fileStatePtr->cacheable, &fileStatePtr->openTimeStamp);
  1157.     /* Remove srcClient from recov box if it was its last handle ref. */
  1158.     if (recov_Transparent && closeSrcClient &&
  1159.         migInfoPtr->srcClientID != rpc_SpriteID) {
  1160.         if (Fsrecov_DeleteHandle((Fs_HandleHeader *) handlePtr,
  1161.             migInfoPtr->srcClientID, migInfoPtr->flags) != SUCCESS) {
  1162.         /* Do better than this. */
  1163.         panic("Fsio_FileMigrate: couldn't delete ioHandle from box.");
  1164.         }
  1165.     }
  1166.     /* Add the dstClient to box if this is a new stream for it. */
  1167.     if (recov_Transparent && (migInfoPtr->flags & FS_NEW_STREAM) &&
  1168.         dstClientID != rpc_SpriteID) {
  1169.         if (Fsrecov_AddHandle((Fs_HandleHeader *) handlePtr,
  1170.             (Fs_FileID *) NIL, dstClientID,
  1171.             migInfoPtr->flags & ~FS_NEW_STREAM,
  1172.             fileStatePtr->cacheable, TRUE) != SUCCESS) {
  1173.         /* Do better. */
  1174.         panic("Fsio_FileMigrate: couldn't add ioHandle to box.");
  1175.         }
  1176.     }
  1177.     if (status == SUCCESS) {
  1178.         Fscache_GetCachedAttr(&handlePtr->cacheInfo, &fileStatePtr->version,
  1179.                 &fileStatePtr->attr);
  1180.         *sizePtr = sizeof(Fsio_FileState);
  1181.         *dataPtr = (Address)fileStatePtr;
  1182.         *flagsPtr = fileStatePtr->newUseFlags = migInfoPtr->flags;
  1183.         *offsetPtr = migInfoPtr->offset;
  1184.     } else {
  1185.         free((Address)fileStatePtr);
  1186.     }
  1187.     /*
  1188.      * We don't need this reference on the I/O handle, there is no change.
  1189.      */
  1190.     Fsutil_HandleRelease(handlePtr, FALSE);
  1191.     }
  1192.     return(status);
  1193. }
  1194.  
  1195. /*
  1196.  *----------------------------------------------------------------------
  1197.  *
  1198.  * Fsio_FileRead --
  1199.  *
  1200.  *    Read from a file.  This is a thin layer on top of the cache
  1201.  *    read routine.
  1202.  *
  1203.  * Results:
  1204.  *    The results of Fscache_Read.
  1205.  *
  1206.  * Side effects:
  1207.  *    None, because Fscache_Read does most everything.
  1208.  *
  1209.  *----------------------------------------------------------------------
  1210.  */
  1211. ReturnStatus
  1212. Fsio_FileRead(streamPtr, readPtr, remoteWaitPtr, replyPtr)
  1213.     Fs_Stream        *streamPtr;    /* Open stream to the file. */
  1214.     Fs_IOParam        *readPtr;    /* Read parameter block. */
  1215.     Sync_RemoteWaiter    *remoteWaitPtr;    /* Process info for remote waiting */
  1216.     Fs_IOReply        *replyPtr;    /* Signal to return, if any,
  1217.                      * plus the amount read. */
  1218. {
  1219.     register Fsio_FileIOHandle *handlePtr =
  1220.         (Fsio_FileIOHandle *)streamPtr->ioHandlePtr;
  1221.     register ReturnStatus status;
  1222.     int savedOffset = readPtr->offset;
  1223.     int savedLength = readPtr->length;
  1224.  
  1225.     status = Fscache_Read(&handlePtr->cacheInfo, readPtr->flags,
  1226.         readPtr->buffer, readPtr->offset, &readPtr->length, remoteWaitPtr);
  1227.     
  1228.     if ((status == SUCCESS) || (readPtr->length > 0)) { 
  1229.     (void)Fsdm_UpdateDescAttr(handlePtr, &handlePtr->cacheInfo.attr,
  1230.                 FSDM_FD_ACCESSTIME_DIRTY);
  1231.     if (readPtr->flags & FS_SWAP) {
  1232.         int hostID = Proc_GetHostID(readPtr->procID);
  1233.         if (hostID == rpc_SpriteID)  {
  1234.         /*
  1235.          * While page-ins on the file server come from its cache, we
  1236.          * inform the cache that these pages are good canidicates
  1237.          * for replacement.
  1238.          */
  1239.         Fscache_BlocksUnneeded(streamPtr, savedOffset, savedLength, 
  1240.                 FALSE);
  1241.         }
  1242.     }
  1243.  
  1244.     }
  1245.     replyPtr->length = readPtr->length;
  1246.     return(status);
  1247. }
  1248.  
  1249. /*
  1250.  *----------------------------------------------------------------------
  1251.  *
  1252.  * Fsio_FileWrite --
  1253.  *
  1254.  *    Write to a disk file.  This is a thin layer on top of the cache
  1255.  *    write routine.  Besides doing the write, this routine synchronizes
  1256.  *    with read ahead on the file.
  1257.  *
  1258.  * Results:
  1259.  *    The results of Fscache_Write.
  1260.  *
  1261.  * Side effects:
  1262.  *    The handle is locked during the I/O.
  1263.  *
  1264.  *----------------------------------------------------------------------
  1265.  */
  1266. ReturnStatus
  1267. Fsio_FileWrite(streamPtr, writePtr, remoteWaitPtr, replyPtr)
  1268.     Fs_Stream        *streamPtr;    /* Open stream to the file. */
  1269.     Fs_IOParam        *writePtr;    /* Read parameter block */
  1270.     Sync_RemoteWaiter    *remoteWaitPtr;    /* Process info for remote waiting */
  1271.     Fs_IOReply        *replyPtr;    /* Signal to return, if any */
  1272. {
  1273.     register Fsio_FileIOHandle *handlePtr =
  1274.         (Fsio_FileIOHandle *)streamPtr->ioHandlePtr;
  1275.     register ReturnStatus status;
  1276.     int savedOffset = writePtr->offset;
  1277.     int savedLength = writePtr->length;
  1278.  
  1279.     /*
  1280.      * Get a reference to the domain so it can't be dismounted during the I/O.
  1281.      * Then synchronize with read ahead before actually doing the write.
  1282.      */
  1283.     if (Fsdm_DomainFetch(handlePtr->hdr.fileID.major, FALSE) ==
  1284.         (Fsdm_Domain *)NIL) {
  1285.     return(FS_DOMAIN_UNAVAILABLE);
  1286.     }
  1287.     Fscache_WaitForReadAhead(&handlePtr->readAhead);
  1288.     status = Fscache_Write(&handlePtr->cacheInfo, writePtr->flags,
  1289.               writePtr->buffer, writePtr->offset,
  1290.               &writePtr->length, remoteWaitPtr);
  1291.     replyPtr->length = writePtr->length;
  1292.     if (status == SUCCESS) {
  1293.     if (replyPtr->length > 0) {
  1294.         (void)Fsdm_UpdateDescAttr(handlePtr, &handlePtr->cacheInfo.attr, 
  1295.             FSDM_FD_MODTIME_DIRTY);
  1296.     }
  1297.     if (writePtr->flags & FS_SWAP) {
  1298.         int hostID = Proc_GetHostID(writePtr->procID);
  1299.         if (hostID == rpc_SpriteID)  {
  1300.         /*
  1301.          * While page-outs on the file server go to its cache, we
  1302.          * inform the cache that these pages are good canidicates
  1303.          * for replacement.
  1304.          */
  1305.          Fscache_BlocksUnneeded(streamPtr, savedOffset, savedLength, 
  1306.                 FALSE);
  1307.         }
  1308.     }
  1309.     }
  1310.  
  1311.     Fscache_AllowReadAhead(&handlePtr->readAhead);
  1312.     Fsdm_DomainRelease(handlePtr->hdr.fileID.major);
  1313.     return(status);
  1314. }
  1315.  
  1316. /*
  1317.  *----------------------------------------------------------------------
  1318.  *
  1319.  * Fsio_FileBlockCopy --
  1320.  *
  1321.  *    Copy the block from the source swap file to the destination swap file.
  1322.  *
  1323.  *    NOTE: This routine does not call the routine that puts swap file blocks
  1324.  *          on the front of the free list.  This is because the general
  1325.  *          mode of doing things is to fork which copies the swap file and
  1326.  *          then exec which removes it.  Thus we want the swap file to be
  1327.  *          in the cache for the copy and we don't have to put the 
  1328.  *          destination files blocks on front of the lru list because it
  1329.  *          is going to get removed real soon anyway.
  1330.  *
  1331.  * Results:
  1332.  *    Error code if couldn't allocate disk space or didn't read a full
  1333.  *    block.
  1334.  *
  1335.  * Side effects:
  1336.  *    None.
  1337.  *
  1338.  *----------------------------------------------------------------------
  1339.  */
  1340. /*ARGSUSED*/
  1341. ReturnStatus
  1342. Fsio_FileBlockCopy(srcHdrPtr, dstHdrPtr, blockNum)
  1343.     Fs_HandleHeader    *srcHdrPtr;    /* File to copy block from.  */
  1344.     Fs_HandleHeader    *dstHdrPtr;    /* File to copy block to.  */
  1345.     int            blockNum;    /* Block to copy. */
  1346. {
  1347.     int            offset;
  1348.     ReturnStatus    status;
  1349.     Fscache_Block    *cacheBlockPtr;
  1350.     int            numBytes;
  1351.     register Fsio_FileIOHandle *srcHandlePtr =
  1352.         (Fsio_FileIOHandle *)srcHdrPtr;
  1353.     register Fsio_FileIOHandle *dstHandlePtr =
  1354.         (Fsio_FileIOHandle *)dstHdrPtr;
  1355.  
  1356.     /*
  1357.      * Look in the cache for the source block.
  1358.      */
  1359.     status = Fscache_BlockRead(&srcHandlePtr->cacheInfo, blockNum,
  1360.             &cacheBlockPtr, &numBytes, FSCACHE_DATA_BLOCK, FALSE);
  1361.     if (status != SUCCESS) {
  1362.     return(status);
  1363.     }
  1364.     if (numBytes != FS_BLOCK_SIZE) {
  1365.     if (numBytes != 0) {
  1366.         Fscache_UnlockBlock(cacheBlockPtr, 0, -1, 0,
  1367.             FSCACHE_CLEAR_READ_AHEAD);
  1368.     }
  1369.     return(VM_SHORT_READ);
  1370.     }
  1371.     /*
  1372.      * Write to the destination block.
  1373.      */
  1374.     numBytes = FS_BLOCK_SIZE;
  1375.     offset = blockNum * FS_BLOCK_SIZE;
  1376.     status = Fscache_Write(&dstHandlePtr->cacheInfo, FALSE,
  1377.             cacheBlockPtr->blockAddr, offset, &numBytes,
  1378.             (Sync_RemoteWaiter *) NIL);
  1379.     if (status == SUCCESS && numBytes != FS_BLOCK_SIZE) {
  1380.  
  1381.     status = VM_SHORT_WRITE;
  1382.     }
  1383.  
  1384.     Fscache_UnlockBlock(cacheBlockPtr, 0, -1, 0, FSCACHE_CLEAR_READ_AHEAD);
  1385.  
  1386.     srcHandlePtr->cacheInfo.attr.accessTime = Fsutil_TimeInSeconds();
  1387.     dstHandlePtr->cacheInfo.attr.modifyTime = Fsutil_TimeInSeconds();
  1388.     (void)Fsdm_UpdateDescAttr(srcHandlePtr, &srcHandlePtr->cacheInfo.attr, 
  1389.             FSDM_FD_ACCESSTIME_DIRTY);
  1390.     (void)Fsdm_UpdateDescAttr(dstHandlePtr, &dstHandlePtr->cacheInfo.attr, 
  1391.             FSDM_FD_MODTIME_DIRTY);
  1392.  
  1393.     return(status);
  1394. }
  1395.  
  1396. /*
  1397.  *----------------------------------------------------------------------
  1398.  *
  1399.  * Fsio_FileIOControl --
  1400.  *
  1401.  *    IOControls for regular files.  The handle should be locked up entry.
  1402.  *    This handles byte swapping of its input and output buffers if
  1403.  *    the clients byte ordering/padding is different.
  1404.  *
  1405.  * Results:
  1406.  *    An error code from the command.
  1407.  *
  1408.  * Side effects:
  1409.  *    Command dependent.
  1410.  *
  1411.  *----------------------------------------------------------------------
  1412.  */
  1413.  
  1414. /*ARGSUSED*/
  1415. ReturnStatus
  1416. Fsio_FileIOControl(streamPtr, ioctlPtr, replyPtr)
  1417.     Fs_Stream *streamPtr;        /* Stream to local file */
  1418.     Fs_IOCParam *ioctlPtr;        /* I/O Control parameter block */
  1419.     Fs_IOReply *replyPtr;        /* Return length and signal */
  1420. {
  1421.     register Fsio_FileIOHandle *handlePtr =
  1422.         (Fsio_FileIOHandle *)streamPtr->ioHandlePtr;
  1423.     register ReturnStatus status = SUCCESS;
  1424.     Boolean    unLock;
  1425.  
  1426.     Fsutil_HandleLock(handlePtr);
  1427.     unLock = TRUE;
  1428.     switch(ioctlPtr->command) {
  1429.     case IOC_REPOSITION:
  1430.         break;
  1431.     case IOC_GET_FLAGS:
  1432.         if ((ioctlPtr->outBufSize >= sizeof(int)) &&
  1433.         (ioctlPtr->outBuffer != (Address)NIL)) {
  1434.         *(int *)ioctlPtr->outBuffer = 0;
  1435.         }
  1436.         break;
  1437.     case IOC_SET_FLAGS:
  1438.     case IOC_SET_BITS:
  1439.     case IOC_CLEAR_BITS:
  1440.         break;
  1441. #ifdef 0
  1442.     case IOC_MAP:
  1443. #endif
  1444.     case IOC_TRUNCATE: {
  1445.         int arg;        /* The truncation length for IOC_TRUNCATE,
  1446.                  * The mapping flag for IOC_MAP. */
  1447.  
  1448.         if (ioctlPtr->inBufSize < sizeof(int)) {
  1449.         status = GEN_INVALID_ARG;
  1450.         } else if ((streamPtr->flags & FS_WRITE) == 0) {
  1451.         status = FS_NO_ACCESS;
  1452.         } else if (handlePtr->descPtr->fileType == FS_DIRECTORY) {
  1453.         status = FS_IS_DIRECTORY;
  1454.         } else if (ioctlPtr->format != mach_Format) {
  1455.         int outSize = sizeof(int);
  1456.         int inSize = sizeof(int);
  1457.         int fmtStatus;
  1458.         fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize, 
  1459.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1460.                 (Address) &arg);
  1461.         if (fmtStatus != 0) {
  1462.             printf("Format of ioctl failed <0x%x>\n", fmtStatus);
  1463.             status = GEN_INVALID_ARG;
  1464.         }
  1465.         if (outSize != sizeof(int)) {
  1466.             status = GEN_INVALID_ARG;
  1467.         }
  1468.         } else {
  1469.         arg = *(int *)ioctlPtr->inBuffer;
  1470.         }
  1471.         if (status == SUCCESS) {
  1472.         if (ioctlPtr->command == IOC_TRUNCATE) {
  1473.             if (arg < 0) {
  1474.             status = GEN_INVALID_ARG;
  1475.             } else {
  1476.             status = Fsio_FileTrunc(handlePtr, arg, 0);
  1477.             }
  1478.         } else {
  1479.             Fsutil_HandleUnlock(handlePtr);
  1480.             unLock = FALSE;
  1481.             status = Fsconsist_MappedConsistency(handlePtr,
  1482.                 ioctlPtr->uid, arg);
  1483.         }
  1484.         }
  1485.         break;
  1486.     }
  1487.     case IOC_LOCK:
  1488.     case IOC_UNLOCK:
  1489.         status = Fsio_IocLock(&handlePtr->lock, ioctlPtr,
  1490.                 &streamPtr->hdr.fileID);
  1491.         break;
  1492.     case IOC_NUM_READABLE: {
  1493.         /*
  1494.          * Return the number of bytes available to read.  The top-level
  1495.          * IOControl routine has put the current stream offset in inBuffer.
  1496.          */
  1497.         int bytesAvailable;
  1498.         int streamOffset;
  1499.         int size;
  1500.  
  1501.         if (ioctlPtr->inBufSize != sizeof(int)) {
  1502.         status = GEN_INVALID_ARG;
  1503.         } else if (ioctlPtr->format != mach_Format) {
  1504.         int fmtStatus;
  1505.         int inSize;
  1506.         inSize = ioctlPtr->inBufSize;
  1507.         fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize, 
  1508.                 ioctlPtr->inBuffer, mach_Format, &size,
  1509.                 (Address) &streamOffset);
  1510.         if (fmtStatus != 0) {
  1511.             printf("Format of ioctl failed <0x%x>\n", fmtStatus);
  1512.             status = GEN_INVALID_ARG;
  1513.         }
  1514.         if (size != sizeof(int)) {
  1515.             status = GEN_INVALID_ARG;
  1516.         }
  1517.         } else {
  1518.         streamOffset = *(int *)ioctlPtr->inBuffer;
  1519.         }
  1520.         if (status == SUCCESS) {
  1521.         bytesAvailable = handlePtr->cacheInfo.attr.lastByte + 1 -
  1522.                 streamOffset;
  1523.         if (ioctlPtr->outBufSize != sizeof(int)) {
  1524.             status = GEN_INVALID_ARG;
  1525.         } else if (ioctlPtr->format != mach_Format) {
  1526.             int fmtStatus;
  1527.             int    inSize;
  1528.             inSize = sizeof(int);
  1529.             fmtStatus = Fmt_Convert("w", mach_Format, &inSize, 
  1530.                     (Address) &bytesAvailable, ioctlPtr->format,
  1531.                     &size, ioctlPtr->outBuffer);
  1532.             if (fmtStatus != 0) {
  1533.             printf("Format of ioctl failed <0x%x>\n", fmtStatus);
  1534.             status = GEN_INVALID_ARG;
  1535.             }
  1536.             if (size != sizeof(int)) {
  1537.             status = GEN_INVALID_ARG;
  1538.             }
  1539.         } else {
  1540.             *(int *)ioctlPtr->outBuffer = bytesAvailable;
  1541.         }
  1542.         }
  1543.         break;
  1544.     }
  1545.     case IOC_SET_OWNER:
  1546.     case IOC_GET_OWNER:
  1547.         status = GEN_NOT_IMPLEMENTED;
  1548.         break;
  1549.     case IOC_PREFIX:
  1550.         break;
  1551.     case IOC_WRITE_BACK: {
  1552.         /*
  1553.          * Write out the cached data for the file.
  1554.          */
  1555.         Ioc_WriteBackArgs *argPtr = (Ioc_WriteBackArgs *)ioctlPtr->inBuffer;
  1556.         Fscache_FileInfo *cacheInfoPtr = &handlePtr->cacheInfo;
  1557.  
  1558.         if (ioctlPtr->inBufSize < sizeof(Ioc_WriteBackArgs)) {
  1559.         status = GEN_INVALID_ARG;
  1560.         } else {
  1561.         int firstBlock, lastBlock;
  1562.         int blocksSkipped;
  1563.         int flags = 0;
  1564.         Ioc_WriteBackArgs writeBack;
  1565.  
  1566.         if (ioctlPtr->format != mach_Format) {
  1567.             int fmtStatus;
  1568.             int size;
  1569.             size = ioctlPtr->inBufSize;
  1570.             fmtStatus = Fmt_Convert("w3", ioctlPtr->format, &size, 
  1571.                     ioctlPtr->inBuffer, mach_Format, &size,
  1572.                     (Address) &writeBack);
  1573.             if (fmtStatus != 0) {
  1574.             printf("Format of ioctl failed <0x%x>\n", fmtStatus);
  1575.             status = GEN_INVALID_ARG;
  1576.             }
  1577.             if (size != sizeof(Ioc_WriteBackArgs)) {
  1578.             status = GEN_INVALID_ARG;
  1579.             }
  1580.             if (status != SUCCESS) {
  1581.             break;
  1582.             }
  1583.             argPtr = &writeBack;
  1584.         }
  1585.         if (argPtr->shouldBlock) {
  1586.             flags |= FSCACHE_FILE_WB_WAIT;
  1587.         }
  1588.         if (argPtr->firstByte > 0) {
  1589.             firstBlock = argPtr->firstByte / FS_BLOCK_SIZE;
  1590.         } else {
  1591.             firstBlock = 0;
  1592.         }
  1593.         if (argPtr->lastByte > 0) {
  1594.             lastBlock = argPtr->lastByte / FS_BLOCK_SIZE;
  1595.         } else {
  1596.             lastBlock = FSCACHE_LAST_BLOCK;
  1597.         }
  1598.         /*
  1599.          * Release the handle lock during the FileWriteBack to 
  1600.          * avoid hanging up everyone who stumbles over the handle
  1601.          * during the writeback.
  1602.          */
  1603.         Fsutil_HandleUnlock(handlePtr);
  1604.         unLock = FALSE;
  1605.         status = Fscache_FileWriteBack(cacheInfoPtr, firstBlock,
  1606.             lastBlock, flags, &blocksSkipped);
  1607.         }
  1608.         break;
  1609.     }
  1610.     default:
  1611.         status = GEN_INVALID_ARG;
  1612.         break;
  1613.     }
  1614.     if (unLock) { 
  1615.     Fsutil_HandleUnlock(handlePtr);
  1616.     }
  1617.     return(status);
  1618. }
  1619.  
  1620. /*
  1621.  *----------------------------------------------------------------------
  1622.  *
  1623.  * Fsio_FileTrunc --
  1624.  *
  1625.  *    Shorten a file to length bytes.  This calls routines to update
  1626.  *    the cacheInfo and the fileDescriptor.
  1627.  *
  1628.  * Results:
  1629.  *    Error status from Fsdm_FileTrunc.
  1630.  *
  1631.  * Side effects:
  1632.  *    None.
  1633.  *
  1634.  *----------------------------------------------------------------------
  1635.  */
  1636.  
  1637. ReturnStatus
  1638. Fsio_FileTrunc(handlePtr, size, flags)
  1639.     Fsio_FileIOHandle    *handlePtr;    /* File to truncate. */
  1640.     int            size;        /* Size to truncate the file to. */
  1641.     int            flags;        /* FSCACHE_TRUNC_DELETE */
  1642. {
  1643.     ReturnStatus status;
  1644.  
  1645.     status = Fscache_Trunc(&handlePtr->cacheInfo, size, flags);
  1646.     if ((flags & FSCACHE_TRUNC_DELETE) == 0) {
  1647.     (void)Fsdm_UpdateDescAttr(handlePtr, &handlePtr->cacheInfo.attr, 
  1648.             FSDM_FD_MODTIME_DIRTY);
  1649.     }
  1650.     return(status);
  1651. }
  1652.  
  1653. /*
  1654.  *----------------------------------------------------------------------
  1655.  *
  1656.  * Fsio_FileSelect --
  1657.  *
  1658.  *    Always returns that file is readable and writable.
  1659.  *
  1660.  * Results:
  1661.  *    SUCCESS        - always returned.
  1662.  *
  1663.  * Side effects:
  1664.  *    None.
  1665.  *
  1666.  *----------------------------------------------------------------------
  1667.  */
  1668. /*ARGSUSED*/
  1669. ReturnStatus
  1670. Fsio_FileSelect(hdrPtr, waitPtr, readPtr, writePtr, exceptPtr)
  1671.     Fs_HandleHeader *hdrPtr;    /* The handle of the file */
  1672.     Sync_RemoteWaiter *waitPtr;    /* Process info for waiting */
  1673.     int        *readPtr;    /* Read bit */
  1674.     int        *writePtr;    /* Write bit */
  1675.     int        *exceptPtr;    /* Exception bit */
  1676. {
  1677.     *exceptPtr = 0;
  1678.     return(SUCCESS);
  1679. }
  1680.  
  1681. /*
  1682.  *----------------------------------------------------------------------------
  1683.  *
  1684.  * IncVersionNumber --
  1685.  *
  1686.  *    Increment the version number on file.  This is done when a file
  1687.  *    is opened for writing, and the version number is used by clients
  1688.  *    to verify their caches.  This must be called with the handle locked.
  1689.  *
  1690.  * Results:
  1691.  *    None.
  1692.  *
  1693.  * Side effects:
  1694.  *    Version number incremented and the descriptor is pushed to disk.
  1695.  *
  1696.  *----------------------------------------------------------------------------
  1697.  *
  1698.  */
  1699. void
  1700. IncVersionNumber(handlePtr)
  1701.     Fsio_FileIOHandle    *handlePtr;
  1702. {
  1703.     Fsdm_FileDescriptor    *descPtr;
  1704.  
  1705.     descPtr = handlePtr->descPtr;
  1706.     descPtr->version++;
  1707.     handlePtr->cacheInfo.version = descPtr->version;
  1708.     descPtr->flags |= FSDM_FD_VERSION_DIRTY;
  1709.     (void)Fsdm_FileDescStore(handlePtr, FALSE);
  1710.     Vm_FileChanged(&handlePtr->segPtr);
  1711. }
  1712.  
  1713.  
  1714. /*
  1715.  *----------------------------------------------------------------------
  1716.  *
  1717.  * Fsio_FileRecovTestUseCount --
  1718.  *
  1719.  *    For recovery testing, return the use count on the file's io handle.
  1720.  *
  1721.  * Results:
  1722.  *    Use count.
  1723.  *
  1724.  * Side effects:
  1725.  *    None.
  1726.  *
  1727.  *----------------------------------------------------------------------
  1728.  */
  1729. int
  1730. Fsio_FileRecovTestUseCount(handlePtr)
  1731.     Fsio_FileIOHandle    *handlePtr;
  1732. {
  1733.     return handlePtr->use.ref;
  1734. }
  1735.  
  1736.  
  1737. /*
  1738.  *----------------------------------------------------------------------
  1739.  *
  1740.  * Fsio_FileRecovTestNumCacheBlocks --
  1741.  *
  1742.  *    For recovery testing, return the number of blocks in the cache
  1743.  *    for this file.
  1744.  *
  1745.  * Results:
  1746.  *    Number of blocks.
  1747.  *
  1748.  * Side effects:
  1749.  *    None.
  1750.  *
  1751.  *----------------------------------------------------------------------
  1752.  */
  1753. int
  1754. Fsio_FileRecovTestNumCacheBlocks(handlePtr)
  1755.     Fsio_FileIOHandle    *handlePtr;
  1756. {
  1757.     return handlePtr->cacheInfo.blocksInCache;
  1758. }
  1759.  
  1760.  
  1761. /*
  1762.  *----------------------------------------------------------------------
  1763.  *
  1764.  * Fsio_FileRecovTestNumDirtyCacheBlocks --
  1765.  *
  1766.  *    For recovery testing, return the number of dirty blocks in the cache
  1767.  *    for this file.
  1768.  *
  1769.  * Results:
  1770.  *    Number of dirty blocks.
  1771.  *
  1772.  * Side effects:
  1773.  *    None.
  1774.  *
  1775.  *----------------------------------------------------------------------
  1776.  */
  1777. int
  1778. Fsio_FileRecovTestNumDirtyCacheBlocks(handlePtr)
  1779.     Fsio_FileIOHandle    *handlePtr;
  1780. {
  1781.     return handlePtr->cacheInfo.numDirtyBlocks;
  1782. }
  1783.  
  1784.  
  1785. /*
  1786.  *----------------------------------------------------------------------
  1787.  *
  1788.  * Fsio_FileSetupHandle --
  1789.  *
  1790.  *    Given a file recovery object, setup the necessary handle state for it.
  1791.  *
  1792.  * Results:
  1793.  *    None.
  1794.  *
  1795.  * Side effects:
  1796.  *    A handle is created in put in the handle table.
  1797.  *
  1798.  *----------------------------------------------------------------------
  1799.  */
  1800. ReturnStatus
  1801. Fsio_FileSetupHandle(recovInfoPtr)
  1802.     Fsrecov_HandleState    *recovInfoPtr;
  1803. {
  1804.     Fsdm_Domain        *domainPtr;
  1805.     Fsio_FileIOHandle    *handlePtr;
  1806.     int            clientID;
  1807.     ReturnStatus    status;
  1808.     int            ref, write, exec;
  1809.     int            useFlags;
  1810.     Fs_FileID        fid;
  1811.  
  1812.     if (!recov_Transparent) {
  1813.     panic("Fsio_FileSetupHandle shouldn't have been called.");
  1814.     }
  1815.  
  1816.     fid = recovInfoPtr->fileID;
  1817.     clientID = fid.serverID;
  1818.     fid.serverID = rpc_SpriteID;
  1819.     domainPtr = Fsdm_DomainFetch(fid.major, FALSE);
  1820.     if (domainPtr == (Fsdm_Domain *) NIL) {
  1821. #ifdef NOTDEF
  1822.     return FS_DOMAIN_UNAVAILABLE;
  1823. #endif NOTDEF
  1824.     panic("Fsio_FileSetupHandle: domain unavailable.");
  1825.     }
  1826.     status = Fsio_LocalFileHandleInit(&fid, (char *) NIL,
  1827.         (Fsdm_FileDescriptor *) NIL, FALSE, &handlePtr);
  1828.     if (status != SUCCESS) {
  1829.     Fsdm_DomainRelease(fid.major);
  1830.     printf ("Status: 0x%x\n", status);
  1831.     panic("Fsio_FileSetupHandle: handle init failed.");
  1832.     }
  1833.     /* Cache consistency checks should be unnecessary. */
  1834.  
  1835.     /*
  1836.      * If necessary, I could use cacheable and use.write to say the
  1837.      * thing MAY have dirty blocks and do a consistency call back just in
  1838.      * case.  To see if this is necessary, I need to see if write-back will
  1839.      * go ahead when processes are kicked on the client, or whether I need
  1840.      * to get the blocks via a consistency call.  Test this!!! XXX
  1841.      */
  1842.  
  1843.     ref = recovInfoPtr->use.ref;
  1844.     write = recovInfoPtr->use.write;
  1845.     exec = recovInfoPtr->use.exec;
  1846.     if (ref > 0) {
  1847.     while (ref > 0) {
  1848.         useFlags = 0;
  1849.         if (write > 0) {
  1850.         useFlags |= FS_WRITE;
  1851.         }
  1852.         if (exec > 0) {
  1853.         useFlags |= FS_EXECUTE;
  1854.         }
  1855.         /* Client data is whether it's cacheable or not. */
  1856.         Fsconsist_UpdateFileConsistencyList(handlePtr, clientID, useFlags,
  1857.             recovInfoPtr->clientData);
  1858.         ref--;
  1859.         write--;
  1860.         exec--;
  1861.     }
  1862.     } else {
  1863.     /* Add to client list with 0 references. */
  1864.     Fsconsist_IOClientAdd(&(handlePtr->consist.clientList), clientID,
  1865.         recovInfoPtr->clientData);
  1866.     }
  1867.     handlePtr->use.ref += recovInfoPtr->use.ref;
  1868.     handlePtr->use.write += recovInfoPtr->use.write;
  1869.     handlePtr->use.exec += recovInfoPtr->use.exec;
  1870.     if (handlePtr->descPtr->version != recovInfoPtr->info) {
  1871.     panic("Fsio_FileSetupHandle: version on file is wrong.\n");
  1872.     }
  1873.     /*
  1874.      * Successful re-open here on the server. Copy cached attributes
  1875.      * into the returned file state.
  1876.      */
  1877.     Fsutil_HandleRelease(handlePtr, TRUE);
  1878.     Fsdm_DomainRelease(fid.major);
  1879.  
  1880.     return SUCCESS;
  1881. }
  1882.